<script>
import { getHouseInfo, getOriginImg, houimgEdit, houimgRevert, updateImage } from '@/api/user';

let canvas;
export default {
  name: 'DialogWaterMarkNew',
  props: {
    houDelId: {
      type: String,
      default: '',
    },
  },
  components: {},
  data() {
    this.maskBase64 = '';
    this.modified = false;
    this.base = 110;
    return {
      imgListDomWidth: 0,
      imgListDomLeft: 0,
      selectIndex: 0, //当前选中的图片
      houImageVO: [],
      loading: false,
      imgUrl: '',
      imgData: {
        width: 0, //页面中展示的宽高
        height: 0,
        resourceWidth: 0, //图片资源宽高
        resourceHeight: 0,
      },
      // 框选正在移动
      cropMoving: false,
      // 框选正在变化尺寸
      cropResizing: false,
      // 选框数据
      cropData: {
        x: 0,
        y: 0,
        w: 0,
        h: 0,
        mouseX: 0, //鼠标的临时坐标
        mouseY: 0,
        oldW: 0, //上次的宽高
        oldH: 0,
        curIndex: -1, //当前拖拽中的锚点
      },
      config: {
        maxWidth: 500,
        maxHeight: 375,
      },
      // 鼠标按下时的临时事件对象
      mouseEvent: {
        clientX: 0,
        clientY: 0,
      },
    };
  },
  render() {
    let { config, imgUrl, cropData, imgData, loading } = this;
    let { width, height } = imgData;
    let boxStyle = {
      width: config.maxWidth + 'px',
      height: config.maxHeight + 'px',
    };
    let imgStyle = {
      width: width + 'px',
      height: height + 'px',
    };

    let hidden = this.cropData.w > 0 || this.cropData.h > 0 ? '' : 'hidden';
    let cropStyle = {
      width: cropData.w + 'px',
      height: cropData.h + 'px',
      left: cropData.x + 'px',
      top: cropData.y + 'px',
    };

    const imgDoms = this.getHouseImages();
    const imgListDomWidth = (this.imgListDomWidth = imgDoms.length * this.base);
    const imgDomsStyle = {
      width: imgListDomWidth + 'px',
      left: this.imgListDomLeft + 'px',
    };
      // <div style="width: 100px; background: salmon"></div>

    return (
      <div class="wrap">
        <div class="body" v-loading={loading} element-loading-background="rgba(0, 0, 0, 0.7)">
          <div class="d-flex">
            <div class="box" style={boxStyle}>
              <img class="img" style={imgStyle} src={imgUrl} />
              <div class="main" onMousedown={this.handleStartCrop}>
                <div class={`crop ${hidden}`} style={cropStyle} onMousedown={this.handleStartMove}>
                  {this.getDragableDoms()}
                </div>
              </div>
            </div>

            <div class="d-flex fd-column flex-1">
              <el-button type="primary" onClick={this.handleSave} disabled={!this.houImageVO.length}>
                去除实勘牌
              </el-button>
              <el-button type="primary" onClick={this.handleRestore} disabled={!this.houImageVO.length}>
                还原图片
              </el-button>
              <el-button type="primary" onClick={this.handleRemove} disabled={!this.houImageVO.length}>
                删除图片
              </el-button>
              <el-button type="primary" onClick={this.handleReset} disabled={!this.houImageVO.length}>
                清除选区
              </el-button>
              <div style="padding: 0 20px">
                <p>第一步：在图片上拖动鼠标选择要去除实勘牌的区域</p>
                <p>第二步：点击“去除实堪牌”即可</p>
              </div>
            </div>
          </div>

          <div class="d-flex" style="margin-top: 20px">
            <el-button
              type="info"
              icon="el-icon-caret-left"
              onClick={this.handleImgScroll.bind(this, 'right')}
            ></el-button>
            <div class="img-wrap flex-1">
              <div class="img-scroll" style={imgDomsStyle}>
                {imgDoms}
              </div>
            </div>
            <el-button
              type="info"
              icon="el-icon-caret-right"
              onClick={this.handleImgScroll.bind(this, 'left')}
            ></el-button>
          </div>
        </div>
      </div>
    );
  },
  async mounted() {
    this.loading = true;
    const data = await getHouseInfo({ houDelId: this.houDelId });
    const houImageVO = (this.houImageVO = data.content.houImageVO);

    if (houImageVO.length) {
      this.selectIndex = 0;
      const { content } = await getOriginImg(houImageVO[this.selectIndex]);
      this.imgUrl = content.originUrl;
      await this.renderImg(this.imgUrl);
    }

    this.loading = false;
  },

  methods: {
    handleImgScroll(type) {
      let base = this.base;
      let v = type == 'left' ? -1 : 1;
      let newLeft = this.imgListDomLeft + base * v;

      this.updateNewLeft(newLeft);
    },

    updateNewLeft(left) {
      if (this.imgListDomWidth > this.base * 6) {
        this.imgListDomLeft = Math.max(Math.min(0, left), -1 * this.imgListDomWidth + this.base * 6);
      }
    },

    locationAuto(i) {
      let num = i - 1;
      if (num < 0) return;
      this.updateNewLeft(-1 * this.base * num);
    },

    getHouseImages() {
      return this.houImageVO.map((item, i) => {
        return (
          <el-image
            class={['img-item', this.selectIndex == i ? 'select' : '']}
            src={item.url}
            fit="fit"
            onClick={this.handleSelectImg.bind(this, i)}
          ></el-image>
        );
      });
    },
    async handleSelectImg(index) {
      this.locationAuto(index);
      this.handleReset();
      this.loading = true;
      this.selectIndex = index;
      const { content } = await getOriginImg(this.houImageVO[index]);
      this.imgUrl = content.originUrl;
      await this.renderImg(this.imgUrl);
      this.loading = false;
    },
    async handleSave() {
      if (!this.maskBase64) {
        return this.$message.error('请先框选区域');
      }

      try {
        this.loading = true;
        let imgInfo = this.houImageVO[this.selectIndex];
        const { content } = await houimgEdit({ ...imgInfo, maskBase64: this.maskBase64 });
        this.imgUrl = content.originUrl;
        this.renderImg(this.imgUrl);
        this.houImageVO.splice(this.selectIndex, 1, content);

        await updateImage({ houImgList: [...this.houImageVO] });

        this.$message.success('去除水印成功!');
      } catch (error) {
        this.$message.error(error);
      }

      this.modified = true;
      this.handleReset();

      this.loading = false;
    },

    // 还原图片
    async handleRestore() {
      this.loading = true;
      try {
        const { content } = await houimgRevert(this.houImageVO[this.selectIndex]);
        this.imgUrl = content.originUrl;
        this.renderImg(this.imgUrl);
        this.houImageVO.splice(this.selectIndex, 1, content);

        await updateImage({ houImgList: [...this.houImageVO] });
      } catch (error) {
        console.log(error);
      }

      this.modified = true;
      this.$message.success('还原成功！');
      this.loading = false;
    },

    async handleRemove() {
      const { houImageVO } = this;
      if (houImageVO.length == 1) {
        return this.$message.error('至少保留一张图片！');
      }

      this.loading = true;

      this.handleReset();
      houImageVO.splice(this.selectIndex, 1);
      await updateImage({ houImgList: [...houImageVO] });

      this.selectIndex = 0;
      const { content } = await getOriginImg(houImageVO[this.selectIndex]);
      this.imgUrl = content.originUrl;
      await this.renderImg(this.imgUrl);
      this.modified = true;

      this.loading = false;
    },

    async renderImg(url) {
      const { width, height } = await this.getImageSize(url);
      this.imgData.resourceWidth = width;
      this.imgData.resourceHeight = height;

      let arr = this.initImageWH(width, height);
      this.imgData.width = arr[0];
      this.imgData.height = arr[1];
    },

    drawCanvasContent() {
      const { imgData } = this;
      let { x, y, w, h } = this.getCropInfoRelativeOriginImage();
      canvas = canvas || document.createElement('canvas');
      canvas.width = imgData.resourceWidth;
      canvas.height = imgData.resourceHeight;
      const ctx = canvas.getContext('2d');

      ctx.clearRect(0, 0, imgData.resourceWidth, imgData.resourceHeight);
      ctx.fillStyle = 'rgb(0,0,0)';
      ctx.fillRect(0, 0, imgData.resourceWidth, imgData.resourceHeight);
      ctx.fillStyle = 'rgb(255,255,255)';
      ctx.fillRect(x, y, w, h);
      this.maskBase64 = [x, y, w, h].join(',');
    },
    // 获取相对原图选区信息
    getCropInfoRelativeOriginImage() {
      const { imgData, config, cropData } = this;
      // 宽铺满
      let isWidthFull = imgData.width == config.maxWidth;
      let dissX = isWidthFull ? 0 : (config.maxWidth - imgData.width) / 2;
      let dissY = isWidthFull ? (config.maxHeight - imgData.height) / 2 : 0;

      let scale = imgData.resourceWidth / imgData.width;
      let x = cropData.x - dissX;
      let y = cropData.y - dissY;
      let w = cropData.w;
      let h = cropData.h;
      if (x < 0) {
        w = w + x;
        x = 0;
      }
      if (y < 0) {
        h = h + y;
        y = 0;
      }
      return {
        x: Math.floor(x * scale),
        y: Math.floor(y * scale),
        w: Math.floor(w * scale),
        h: Math.floor(h * scale),
      };
    },
    handleReset() {
      this.cropData.w = 0;
      this.cropData.h = 0;

      this.maskBase64 = '';
    },
    handleResize(i, e) {
      e.preventDefault();
      this.cropResizing = true;
      this.curIndex = i;
      const { cropData, mouseEvent } = this;

      cropData.mouseX = cropData.x;
      cropData.mouseY = cropData.y;
      cropData.oldW = cropData.w;
      cropData.oldH = cropData.h;
      mouseEvent.clientX = e.clientX;
      mouseEvent.clientY = e.clientY;

      window.addEventListener('mousemove', this.resizeCrop);
      window.addEventListener('mouseup', this.endResizeCrop);
    },

    resizeCrop(e) {
      e.preventDefault();

      const { clientX, clientY } = e;
      const { cropData, config, mouseEvent } = this;

      const diffX = clientX - mouseEvent.clientX;
      const diffY = clientY - mouseEvent.clientY;

      // 横轴向左
      function horizontalLeft() {
        cropData.w = Math.min(cropData.oldW - diffX, cropData.oldW + cropData.mouseX);
        if (cropData.w > 0) {
          cropData.x = Math.max(diffX + cropData.mouseX, 0);
        }
      }
      function horizontalRight() {
        cropData.w = Math.min(clientX - mouseEvent.clientX + cropData.oldW, config.maxWidth - cropData.x);
      }
      function verticalTop() {
        cropData.h = Math.min(cropData.oldH - diffY, cropData.oldH + cropData.mouseY);
        if (cropData.h > 0) {
          cropData.y = Math.max(diffY + cropData.mouseY, 0);
        }
      }
      function verticalBottom() {
        cropData.h = Math.min(clientY - mouseEvent.clientY + cropData.oldH, config.maxHeight - cropData.y);
      }

      let cb = null;
      switch (Number(this.curIndex)) {
        case 1:
          cb = () => {
            verticalTop();
            horizontalLeft();
          };
          break;
        case 2:
          cb = () => {
            verticalTop();
          };
          break;
        case 3:
          cb = () => {
            horizontalRight();
            verticalTop();
          };
          break;
        case 4:
          cb = () => {
            horizontalLeft();
          };
          break;
        case 5:
          cb = () => {
            horizontalRight();
          };
          break;
        case 6:
          cb = () => {
            horizontalLeft();
            verticalBottom();
          };
          break;

        case 7:
          cb = () => {
            verticalBottom();
          };
          break;

        case 8:
          cb = () => {
            horizontalRight();
            verticalBottom();
          };
          break;
      }

      this.$nextTick(cb);
    },

    endResizeCrop() {
      this.cropResizing = false;
      window.removeEventListener('mousemove', this.resizeCrop);
      window.removeEventListener('mouseup', this.endResizeCrop);

      this.drawCanvasContent();
    },

    getDragableDoms() {
      let list = ['1', '2', '3', '4', '5', '6', '7', '8'];
      return list.map((item) => {
        return <span class={`crop-point point${item}`} onMousedown={this.handleResize.bind(this, item)}></span>;
      });
    },
    // 鼠标按钮开始移动选区
    handleStartMove(e) {
      e.preventDefault();
      if (this.cropResizing) return;

      const { mouseEvent, cropData } = this;
      this.cropMoving = true;

      cropData.mouseX = cropData.x;
      cropData.mouseY = cropData.y;

      mouseEvent.clientX = e.clientX;
      mouseEvent.clientY = e.clientY;

      window.addEventListener('mousemove', this.moveCrop);
      window.addEventListener('mouseup', this.endMoveCrop);
    },

    moveCrop(e) {
      e.preventDefault();
      const { clientX, clientY } = e;
      const { cropData, config, mouseEvent } = this;

      this.$nextTick(() => {
        cropData.x = Math.min(
          Math.max(clientX - mouseEvent.clientX + cropData.mouseX, 0),
          config.maxWidth - cropData.w,
        );
        cropData.y = Math.min(
          Math.max(clientY - mouseEvent.clientY + cropData.mouseY, 0),
          config.maxHeight - cropData.h,
        );
      });
    },

    endMoveCrop() {
      this.cropMoving = false;

      window.removeEventListener('mousemove', this.moveCrop);
      window.removeEventListener('mouseup', this.endMoveCrop);

      this.drawCanvasContent();
    },

    // 鼠标按下开始建立选区
    handleStartCrop(e) {
      e.preventDefault();
      if (this.cropMoving || this.cropResizing) return;

      const { cropData, mouseEvent } = this;
      if (cropData.w > 0 || cropData.h > 0) return;

      mouseEvent.clientX = e.clientX;
      mouseEvent.clientY = e.clientY;

      cropData.x = e.offsetX;
      cropData.y = e.offsetY;
      cropData.w = 0;
      cropData.h = 0;

      window.addEventListener('mousemove', this.createCrop);
      window.addEventListener('mouseup', this.endCreateCrop);
    },

    createCrop(e) {
      e.preventDefault();
      const { clientX, clientY } = e;
      const { cropData, config, mouseEvent } = this;

      this.$nextTick(() => {
        this.cropData.w = Math.min(clientX - mouseEvent.clientX, config.maxWidth - cropData.x);
        this.cropData.h = Math.min(clientY - mouseEvent.clientY, config.maxHeight - cropData.y);
      });
    },
    endCreateCrop(e) {
      e.preventDefault();

      window.removeEventListener('mousemove', this.createCrop);
      window.removeEventListener('mouseup', this.endCreateCrop);

      this.drawCanvasContent();
    },
    initImageWH(imgW, imgH) {
      let w = this.config.maxWidth;
      let h = this.config.maxHeight;
      let percent = imgW / imgH;

      function mainWidth() {
        imgW = w;
        imgH = imgW / percent;
      }

      function mainHeight() {
        imgH = h;
        imgW = imgH * percent;
      }

      let bool = w / h > imgW / imgH;
      if (bool) {
        mainHeight();
      } else {
        mainWidth();
      }

      return [imgW, imgH];
    },
    getImageSize(src) {
      return new Promise((resolve) => {
        let img = new Image();
        img.onload = () => {
          img.onload = null;
          resolve({
            width: img.width,
            height: img.height,
          });
        };
        img.src = src;
      });
    },
  },
};
</script>

<style scoped>
.wrap {
  position: relative;
  background-color: rgba(0, 0, 0, 0.3);
  display: flex;
}

.body {
  /* width: 800px; */
  background-color: white;
  /* padding: 20px; */
  /* margin: auto; */
}

.body .title {
  font-size: 18px;
  line-height: 24px;
  padding-bottom: 10px;
}

.body .box {
  background-image: url('');
  position: relative;
}
.img {
  opacity: 1;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
.crop {
  position: absolute;
  border: 1px solid rgb(80, 191, 255);
  cursor: move;
  background-color: rgba(80, 291, 255, 0.2);
}
.crop.hidden {
  visibility: hidden;
}
.main {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}
.crop-point {
  position: absolute;
  width: 8px;
  height: 8px;
  opacity: 0.75;
  background-color: #39f;
}

.crop-point.point1 {
  top: -4px;
  left: -4px;
  cursor: nw-resize;
}
.crop-point.point2 {
  top: -5px;
  left: 50%;
  margin-left: -3px;
  cursor: n-resize;
}
.crop-point.point3 {
  top: -4px;
  right: -4px;
  cursor: ne-resize;
}
.crop-point.point4 {
  top: 50%;
  left: -4px;
  margin-top: -3px;
  cursor: w-resize;
}
.crop-point.point5 {
  top: 50%;
  right: -4px;
  margin-top: -3px;
  cursor: e-resize;
}
.crop-point.point6 {
  bottom: -5px;
  left: -4px;
  cursor: sw-resize;
}
.crop-point.point7 {
  bottom: -5px;
  left: 50%;
  margin-left: -3px;
  cursor: s-resize;
}
.crop-point.point8 {
  bottom: -5px;
  right: -4px;
  cursor: se-resize;
}
.tips {
  font-size: 12px;
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  position: absolute;
  top: -20px;
  width: 200px;
}
.wrap >>> .el-button {
  margin: 0;
  margin: 20px;
}
.btn-close {
  font-size: 40px;
  cursor: pointer;
}
.img-wrap {
  overflow: hidden;
  position: relative;
  height: 100px;
  user-select: none;
}

.img-scroll {
  position: absolute;
  transition: all 0.3s;
}

.img-item {
  cursor: pointer;
  width: 100px;
  height: 100px;
  margin-right: 10px;
  border: 2px solid #ccc;
  opacity: 0.8;
}

.img-item.select {
  opacity: 1;
  border-color: red;
}
.wrap >>> .el-button--info {
  margin: 0 10px;
  font-size: 30px;
  padding: 0;
}
</style>
